// regex
#include <iostream>
#include <regex>
#include <string>
#include <iterator>

/*
Functions:

regex_match
    Match sequence (function template )

regex_search
    Search sequence (function template )

regex_replace
    Replace matched sequence (function template )

terator types:

regex_iterator
    Regex iterator (class template )

regex_token_iterator
    Regex token iterator (class template )

Basic types:

basic_regex
    Regular expression (class template )

match_results
    Match results (class template )

sub_match
    Sub-expression match (class template )

regex_traits
    Regex traits (class template )

regex_error
    Regex exception (class )

basic_regex instantiations:

regex
    Regex (class )

wregex
    Regex for wchar_t (class )

match_results instantiations:

cmatch
    match_results for string literals (class )

wcmatch
    match_results for wide string literals (class )

smatch
    match_results for string objects (class )

wsmatch
    match_results for wide string objects (class )

sub_match instantiations:

csub_match
    sub_match for string literals (class )

wcsub_match
    sub_match for wide string literals (class )

ssub_match
    sub_match for strings (class )

wssub_match
    sub_match for wide strings (class )
 */

void use_regex_match()
{
    //reference link: http://www.cplusplus.com/reference/regex/regex_match/
    if (std::regex_match ("subject", std::regex("(sub)(.*)") ))
    std::cout << "string literal matched\n";

    const char cstr[] = "subject";
    std::string s ("subject");
    std::regex e ("(sub)(.*)");

    if (std::regex_match (s,e))
        std::cout << "string object matched\n";

    if ( std::regex_match ( s.begin(), s.end(), e ) )
        std::cout << "range matched\n";

    std::cmatch cm;    // same as std::match_results<const char*> cm;
    std::regex_match (cstr,cm,e);
    std::cout << "string literal with " << cm.size() << " matches\n";

    std::smatch sm;    // same as std::match_results<string::const_iterator> sm;
    std::regex_match (s,sm,e);
    std::cout << "string object with " << sm.size() << " matches\n";

    std::regex_match ( s.cbegin(), s.cend(), sm, e);
    std::cout << "range with " << sm.size() << " matches\n";

    // using explicit flags:
    std::regex_match ( cstr, cm, e, std::regex_constants::match_default );

    std::cout << "the matches were: ";
    for (unsigned i=0; i<cm.size(); ++i) {
        std::cout << "[" << cm[i] << "] ";
    }

    std::cout << std::endl;
}

void use_regex_search()
{
    //reference link: http://www.cplusplus.com/reference/regex/regex_search/
    std::string s ("this subject has a submarine as a subsequence");
    std::smatch m;
    std::regex e ("\\b(sub)([^ ]*)");   // matches words beginning by "sub"

    std::cout << "Target sequence: " << s << std::endl;
    std::cout << "Regular expression: /\\b(sub)([^ ]*)/" << std::endl;
    std::cout << "The following matches and submatches were found:" << std::endl;

    while (std::regex_search (s,m,e)) {
        for (auto x:m) std::cout << x << " ";
        std::cout << std::endl;
        s = m.suffix().str();
    }
}

void use_regex_replace()
{
    //reference link: http://www.cplusplus.com/reference/regex/regex_replace/
    std::string s ("there is a subsequence in the string\n");
    std::regex e ("\\b(sub)([^ ]*)");   // matches words beginning by "sub"

    // using string/c-string (3) version:
    std::cout << std::regex_replace (s,e,"sub-$2");

    // using range/c-string (6) version:
    std::string result;
    std::regex_replace (std::back_inserter(result), s.begin(), s.end(), e, "$2");
    std::cout << result;

    // with flags:
    std::cout << std::regex_replace (s,e,"$1 and $2",std::regex_constants::format_no_copy);
    std::cout << std::endl;

}


int main()
{
    use_regex_match();
    use_regex_search();
    use_regex_replace();
    
    return 0;
}